library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity iram16x32 is
generic (
  block_size : Integer := 32;
  tag_size : Integer := 10;
  index_size : Integer := 4;
  set_size : Integer := 16
);
  port
  (
    clk				:	IN	STD_LOGIC;
    nReset : IN STD_LOGIC;
    addr      : IN  STD_LOGIC_VECTOR (index_size-1 DOWNTO 0);
    we        : IN  STD_LOGIC := '1';
    writeport : IN  STD_LOGIC_VECTOR (block_size+tag_size DOWNTO 0);
    readport  : OUT STD_LOGIC_VECTOR (block_size+tag_size DOWNTO 0)
  );
end iram16x32;


architecture internalRAM of iram16x32 is
  
        type cachestatusbits is array (0 to 15) of std_logic;
        type cachetag    is array (0 to 15) of std_logic_vector(tag_size-1 downto 0);
        type cacheword is array (0 to 15) of std_logic_vector(31 downto 0);
        type cacheram is array (0 to set_size-1) of std_logic_vector (block_size+tag_size downto 0);

        signal cbits : cachestatusbits;
        signal ctag : cachetag;
        signal cword : cacheword;
        signal cram : cacheram;

begin

        ramreg : process (clk, we, addr, nReset)
        begin
                if (nReset = '0') then
                  for i in 0 to set_size-1 loop
                        cram(i) <= (others => '0');
                        cbits(i) <= '0';
                        ctag(i) <= (others => '0');
                        cword(i) <= (others => '0');
                  end loop;
                elsif (rising_edge(clk)) then
                        if (we = '1') then
                                for i in 0 to set_size-1 loop
                                        if (std_logic_vector(to_unsigned(i,addr'length)) = addr) then
                                                cbits(i) <= writeport (42);
                                                ctag(i) <= writeport (41 downto 32);
                                                cword(i) <= writeport (31 downto 0);
                                                cram(i) <= writeport;
                                        end if;
                                end loop;
                        end if;
                end if;
        end process;

        ramread : process (addr,cram, cword, ctag, cbits)
        begin
                readport <= (others => '0');
                for i in 0 to set_size-1 loop
                        if (std_logic_vector(to_unsigned(i,addr'length)) = addr) then
                                readport <= cbits(i) & ctag(i) & cword(i);
                        end if;
                end loop;
        end process;

end internalRAM;
